/********************************************************
 Name          : llc_if.c
 Author        : Khachatur Gyozalyan
 Copyright     : Copyright by Antel Systems
 Description   :
 **********************************************************/

#include "llc_if.h"
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "lwip/stats.h"
#include "lwip/sys.h"
#include "netif/etharp.h"
#include "llc/llc.h"
#include "CfgParams.h"

#define PQUEUE_SIZE 8

struct llcif_t {
	volatile uint8_t rx_pending;

	struct {
		struct pbuf* buf[PQUEUE_SIZE];
		uint8_t first;
		uint8_t last;
	} pqueue;
};

#define LLC_PQUEUE_EMPTY(q) (q.last == q.first)
#define LLC_PQUEUE_FULL(q) ((q.last + 1) % LLC_PQUEUE_SIZE == q.first)
#define LLC_PQUEUE_FIRST(q) (q.buf[q.first])
#define LLC_PQUEUE_DEQUEUE(q)                                               \
        ({                                                              \
                struct pbuf* __p = LLC_PQUEUE_FIRST(q);                     \
                q.first = (q.first + 1) % LLC_PQUEUE_SIZE;                  \
                __p;                                                    \
        })
#define LLC_PQUEUE_ENQUEUE(q, p)                                            \
        ({                                                              \
                q.buf[q.last] = p;                                      \
                q.last = (q.last + 1) % LLC_PQUEUE_SIZE;                    \
        })

struct netif *llc_netif;

/*================================================================================*\
  Author      :       Khachatur Gyozalyan
  ================================================================================
  Function    :       llc_if_init
  Description :       This function llc level should be initialized.
  Return      :       err_t
  Parameters  :       netif - the already initialized lwip network interface.
  Note        :
\*================================================================================*/
static err_t llc_level_init(struct netif *netif)
{
	//netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP |	NETIF_FLAG_LINK_UP;
	netif->flags = NETIF_FLAG_UP;
	netif->hwaddr_len = LLC_HW_ADDR_LEN;

	if (llc_get_hw_addr(netif->hwaddr) != LLC_SUCCESS)
		return ERR_IF;

	/* maximum transfer unit */
	netif->mtu = LLC_MAX_PKT_LEN;

	return ERR_OK;
}

/*================================================================================*\
  Author      :       Khachatur Gyozalyan
  ================================================================================
  Function    :       llc_if_init
  Description :       This function sets up the llc network interface.
  Return      :       err_t
  Parameters  :       netif - the lwip network interface structure for this interface.
  Note        :
\*================================================================================*/
err_t llc_if_init(struct netif *netif)
{
	static struct llcif_t llcif = { 0 };

	netif->state = &llcif;
	netif->name[0] = 'L';
	netif->name[1] = 'L';

	//netif->output = llc_output;//iiiiiiiiiiiiiiiiiiiiiiiiiiiii
	// netif->linkoutput = llc_low_level_output;

	llc_init();

	return llc_level_init(netif);
}

/*================================================================================*\
  Author      :       Khachatur Gyozalyan
  ================================================================================
  Function    :       llc_netif_init
  Description :       This function add llc network interface and initializes it.
  Return      :       int
  Parameters  :       void
  Note        :
\*================================================================================*/
int llc_netif_init(void)
{
	struct ip_addr ipaddr, netmask, gw;

	llc_netif = calloc(1, sizeof(struct netif));

/*	IP4_ADDR(&gw, 192,168,0,1);
	IP4_ADDR(&ipaddr, 192,168,0,10);
	IP4_ADDR(&netmask, 255,255,255,0);*/
/*	ipaddr.addr = ConfigRoot.WirelessLink.WiFiSettings.IP.value;
	gw.addr = ConfigRoot.WirelessLink.WiFiSettings.Gate.value;
	netmask.addr = ConfigRoot.WirelessLink.WiFiSettings.Mask.value;*/


	llc_netif = netif_add(llc_netif,
							&ipaddr,
							&netmask,
							&gw,
							NULL,
							llc_if_init,
							llc_input);

	netif_set_default(llc_netif);
	//netif_set_status_callback(llc_netif, llc_status_cb);

	return 1;
}


/*================================================================================*\
  Author      :       Khachatur Gyozalyan
  ================================================================================
  Function    :       llc_if_poll
  Description :       This function read o packet (if exist).
  Return      :       void
  Parameters  :       void
  Note        :
\*================================================================================*/
void llc_if_poll(void)
{
	struct llcif_t* priv = (struct llcif_t*) llc_netif->state;

	/* llc_if_init() not called yet? */
	if (priv == NULL)
		return;

	/* no packets pending? */
	if (!priv->rx_pending)
		return;

	/* read the pending packet */
	//llc_if_input();

	/* send any packets that was queued due to filled up target queue
	 * or power save mode.
	 */
	//process_pqueue(netif);
}



